package org.gc.amino.ia;

import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;
import org.gc.amino.engine.mote.Mote;
import org.gc.amino.engine.terrainmap.PointD;
import org.gc.amino.ia.httpserver.IaDeliveryInterface;
import org.gc.amino.ia.httpserver.IaLauncher;
import org.gc.amino.universe.Universe;

/**
 * This AI follows the descending gradient of potential in the field.
 */
public class FieldAI implements IaDeliveryInterface {

    private static final Logger log = Logger.getLogger( StupidIa.class );

    private static final int NumberOfDirections = 7;
    
    private Random random = new Random();
    private PointD terrainSize;
    private PointD currentDirection = null;
    private PointD[] cardinal_directions;
    private int moving_counter = 0;
   
    private int idling_counter_max = 20;
    private int idling_counter = idling_counter_max;
    
    public FieldAI() {
    	this.cardinal_directions = new PointD[NumberOfDirections + 1];
    	
    	this.cardinal_directions[0] = new PointD(0, 0);
    	for(int i = 1; i < NumberOfDirections + 1; ++i) {
    		double angle = 2 * Math.PI / i;
    		this.cardinal_directions[i] = new PointD(Math.cos(angle), Math.sin(angle));
    	}
    }
    
    @Override
    public void init( PointD size ) {
        terrainSize = size;
    }
    
    @Override
    public PointD frame( Mote you, List<Mote> otherMotes ) {
        int moving_counter_max = 2;
    	
    	if ( moving_counter > 0 ) {
            moving_counter--;
            return currentDirection;
        } else if ( idling_counter <= 0 ) {
            moving_counter = moving_counter_max;
            idling_counter = idling_counter_max;
            
            Universe universe = new Universe(this.terrainSize, otherMotes, you);
			int best_dir = this.findBestDirection(universe, 2);
			
			MoteSimulator me = universe.getMe();
			PointD best = this.cardinal_directions[best_dir];
            currentDirection = new PointD(me.getPosition().x + me.getSpeed().x - best.x, me.getPosition().y + me.getSpeed().y - best.y);
            
            double dot_product = (best.x * me.getSpeed().x + best.y * me.getSpeed().y) / me.getSpeed().distance(0, 0);
            
            if(dot_product < 0) {
            	moving_counter_max = 6;
            } else {
            	moving_counter_max = 2;
            	if(dot_product > 0.8 && me.getSpeed().distance(0, 0) > 0.45f) {
            		currentDirection = null;
            	}
            }
            
            System.out.println("speed: " + me.getSpeed().distance(0, 0));
            //System.out.println("dot: " + dot_product);
            //System.out.println("chosen dir: (" + currentDirection.x + ", " + currentDirection.y + ")");
            return currentDirection;
            
        } else {
        	idling_counter--;
            return null;
        }
    }

    public int findBestDirection(Universe universe, int courage) {
    	int best = 0;
    	MoteSimulator you = universe.getMe();
    	
    	float probing_dist = you.getRadius();
    	
    	float min_potential = universe.computeFieldPotential(
				you.getRadius(), 
				new Point2D.Float(
					you.getPosition().x + probing_dist * (float)this.cardinal_directions[0].x, 
					you.getPosition().y + probing_dist * (float)this.cardinal_directions[0].y), 
				you,
				courage);
    	
    	for(int direction = 1; direction < NumberOfDirections + 1; ++direction) {
    		float potential = universe.computeFieldPotential(
    				you.getRadius(), 
    				new Point2D.Float(
						you.getPosition().x + (float)this.cardinal_directions[direction].x, 
						you.getPosition().y + (float)this.cardinal_directions[direction].y), 
    				you,
    				courage);
    		if(potential < min_potential) {
    			min_potential = potential;
    			best = direction;
    		}
    	}
    	
    	System.out.println("best dir: " + best + " potential: " + min_potential);
    	
		return best;
    }
    
    public static void main( String[] argv ) throws IOException {
        IaLauncher.launch( argv, new FieldAI(), 1235 );
    }

}
